#include "ProtocolFrameGrabber.h"
#include "HD44780AnalyzerSettings.h"
#include "HD44780Analyzer.h"
#include <AnalyzerChannelData.h>
#include <vector>
#include "PluginConstants.h"

static inline bool IsFrameFlaggedAsError( U8 flag ) { return (flag & FLAG_FRAME_AS_ERROR) == FLAG_FRAME_AS_ERROR; }
static inline bool IsCommandRequestToWrite( U64 data ) { return (data & CMD_MASK_11BITS) == WRITE_REQUEST_FLAG; }
static inline bool IsCommandRequestToReadBusyFlag( U64 data ) { return (data & CMD_MASK_11BITS ) == READ_REQUEST_FLAG;  }
static inline bool IsCommandRequestToReadData( U64 data ) { return ( data & CMD_MASK_11BITS ) == READDATA11BITS; }
static inline bool IsControlCommand( U64 data ) { return ( data & CMD_MASK_11BITS ) == CMD11BITS; }


//HD44780ParallelAnalyzer* ProtocolFrameGrabber::mAnalyzer = NULL;

void ProtocolFrameGrabber::Init( HD44780Analyzer* Analyzer )
{
    mAnalyzer = Analyzer;
}
U8  ProtocolFrameGrabber::GetFrameType( U64 FrameData)
{
    U8 FrameType = ERROR_REQUEST;
    if ( IsCommandRequestToWrite(FrameData) )
        FrameType = WRITE_REQUEST;
    else if ( IsCommandRequestToReadBusyFlag(FrameData) )
        FrameType = BUSY_FLAG_REQUEST;
    else if ( IsCommandRequestToReadData(FrameData) )
        FrameType = READ_DATA_REQUEST;
    else if ( IsControlCommand(FrameData) )
        FrameType = CONTROL_REQUEST;
    return FrameType;
}

void ProtocolFrameGrabber::GrabFrame()
{
     U64 Sample = mAnalyzer->GetClock()->GetSampleNumber();
     mAnalyzer->PositionClockAtCapturePoint();
     U64 Data1 =GetData1();
     if ( !mAnalyzer->IsFramePartOfInitializationSequence( Data1) )
     {
         mAnalyzer->PositionStartMarkerOnChannels();
         mAnalyzer->MoveClockToNextTargetFrameIfPossible();
     }
     else
     {
         mAnalyzer->PositionMarkerOnSingleFrameChannels();
         mAnalyzer->MoveClockToNextTargetFrameIfPossible(); 
     }
     mAnalyzer->StoreFrame( Sample, Data1, GetData2(), GetFlag(), GetFrameType(Data1));
     mAnalyzer->MoveClockToNextTargetFrameIfPossible();
}

U64 ProtocolFrameGrabber::GetData1()
{
    return  mAnalyzer->CalculateDataFromChannels();
}

U64 ProtocolFrameGrabber::GetData2()
{
    return 0;
}

U8 ProtocolFrameGrabber::GetFlag()
{
    return 0;
}

U64 ProtocolFrameGrabber8Bits::GetData1()
{
    return  (mAnalyzer->CalculateDataFromChannels() << 3);
}

U8  ProtocolFrameGrabber8Bits::GetFrameType( U64 FrameData)
{
    U8 FrameType = ERROR_REQUEST;
    if ( IsCommandRequestToWrite(FrameData) )
        FrameType = WRITE_REQUEST_8BITS;
    else if ( IsCommandRequestToReadBusyFlag(FrameData) )
        FrameType = BUSY_FLAG_REQUEST_8BITS;
    else if ( IsCommandRequestToReadData(FrameData) )
        FrameType = READ_DATA_REQUEST_8BITS;
    else if ( IsControlCommand(FrameData) )
        FrameType = CONTROL_REQUEST_8BITS;
    return FrameType;
}


bool ProtocolFrameGrabber7Bits::CommandsFromFirstNibbleIsDifferentThanCommandFromSecondNibble( U64 FirstNibble, U64 SecondNibble )
{
    return (FirstNibble & CMD_MASK_11BITS) != (SecondNibble & CMD_MASK_11BITS) ? true : false;
}
U64 ProtocolFrameGrabber7Bits::MergeNibblesBetweenTwoConsecutive4BitDataCapturePoints( U64 FirstNibble, U64 SecondNibble )
{
    return  FirstNibble | (( SecondNibble >> 4) & 0x0F);
}

void ProtocolFrameGrabber7Bits::GrabFrame()
{
    U64 Sample = mAnalyzer->GetClock()->GetSampleNumber();

    mAnalyzer->PositionClockAtCapturePoint();
    U64 LowerNibble = GetData1();
    U64 HigherNibble = 0;
    U8  Flag = 0;

    if ( !mAnalyzer->IsFramePartOfInitializationSequence(LowerNibble) )
    {
        mAnalyzer->PositionStartMarkerOnChannels();
        mAnalyzer->MoveClockToNextTargetFrame();
        mAnalyzer->PositionClockAtCapturePoint();
        HigherNibble = GetData2();
        if ( CommandsFromFirstNibbleIsDifferentThanCommandFromSecondNibble( LowerNibble, HigherNibble ) )
        {
            mAnalyzer->PositionErrorMarkerOnChannels();
            Flag |= FLAG_FRAME_AS_ERROR;
        }
        else
        {
            mAnalyzer->PositionEndMarkerOnChannels();
            LowerNibble = MergeNibblesBetweenTwoConsecutive4BitDataCapturePoints( LowerNibble, HigherNibble );
        }
        mAnalyzer->MoveClockToNextTargetFrameIfPossible();
        mAnalyzer->StoreFrame( Sample, LowerNibble,HigherNibble, Flag, GetFrameType( ((Flag & FLAG_FRAME_AS_ERROR) == FLAG_FRAME_AS_ERROR) ? 0 :LowerNibble) );
    }
    else
    {
        mAnalyzer->PositionMarkerOnSingleFrameChannels();
        mAnalyzer->MoveClockToNextTargetFrameIfPossible(); 
        mAnalyzer->StoreFrame( Sample, LowerNibble,HigherNibble, Flag, GetFrameType(LowerNibble));
    }

   mAnalyzer-> MoveClockToNextTargetFrameIfPossible();
}

U64 ProtocolFrameGrabber7Bits::GetData1()
{
    return  (mAnalyzer->CalculateDataFromChannels() << 4);
}

U64 ProtocolFrameGrabber7Bits::GetData2()
{
    return  (mAnalyzer->CalculateDataFromChannels() << 4);
}

U8 ProtocolFrameGrabber7Bits::GetFlag()
{
    return 0;
}






